package com.bamboo.tool.view;

import com.bamboo.tool.config.BambooToolComponent;
import com.bamboo.tool.config.model.RestfulCloudConfig;
import com.bamboo.tool.db.entity.BambooApiMethod;
import com.bamboo.tool.factory.FrameworkExecute;
import com.bamboo.tool.store.StoreService;
import com.bamboo.tool.template.export.view.actions.ExportAction;
import com.bamboo.tool.template.torna.view.actions.UploadTornaAction;
import com.bamboo.tool.util.PopupHandler;
import com.bamboo.tool.util.PsiUtils;
import com.bamboo.tool.util.TaskUtil;
import com.bamboo.tool.view.component.actions.*;
import com.bamboo.tool.view.component.tree.ApiTree;
import com.bamboo.tool.view.component.tree.BaseNode;
import com.bamboo.tool.view.component.tree.MethodNode;
import com.bamboo.tool.view.component.tree.RootNode;
import com.intellij.icons.AllIcons;
import com.intellij.ide.CommonActionsManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.speedSearch.SpeedSearchUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

/**
 * @author bamboo
 * Date 2022/10/12 11:59
 * Description
 */
public class ApiNavTool extends SimpleToolWindowPanel implements DataProvider {
    private Project myProject;

    private ApiTree apiTree;

    private JTextField searchField;

    private JPanel mainPanel;

    public ApiNavTool(Project myProject) {
        super(false);
        this.myProject = myProject;
        apiTree = new ApiTree();
        apiTree.setCellRenderer(new MyCellRenderer());

        apiTree.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    navigateToMethod();
                }
            }
        });

        apiTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent event) {
                if (!apiTree.isEnabled()) {
                    return;
                }
                int selectionCount = apiTree.getSelectionCount();
                if (selectionCount < 1) {
                    RootNode root = (RootNode) apiTree.getModel().getRoot();
                    apiTree.setSelectionPath(new TreePath(root));
                }

            }
        });

        apiTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent event) {
                if (event.getClickCount() == 2 && event.getButton() == MouseEvent.BUTTON1) {
                    navigateToMethod();
                }
            }
        });


        searchField = new JTextField();


        searchField.getDocument().addDocumentListener(new DocumentListener() {

            @Override
            public void insertUpdate(DocumentEvent e) {
                filterRefresh();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                filterRefresh();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                filterRefresh();
            }
        });

        TreeSpeedSearch treeSpeedSearch = new TreeSpeedSearch(apiTree, path -> {
            BaseNode node = (BaseNode) path.getLastPathComponent();
            Object object = node.getUserObject();
            return object.toString();
        }, true);
        JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(treeSpeedSearch.getComponent());
        JScrollPane searchPane = ScrollPaneFactory.createScrollPane(searchField);
        mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(searchPane, BorderLayout.BEFORE_FIRST_LINE);
        mainPanel.add(scrollPane, BorderLayout.CENTER);
        setLayout(new BorderLayout());
        initActionBar();

        DefaultActionGroup group = new DefaultActionGroup();

        group.add(new TemplateDebugAction(apiTree));
        group.add(new RenameAction(apiTree));
        group.addSeparator();

        DefaultActionGroup actionGroup = new DefaultActionGroup();
        Presentation templatePresentation = actionGroup.getTemplatePresentation();
        templatePresentation.setText("上传");
        templatePresentation.setDescription("上传第三方");
        templatePresentation.setIcon(AllIcons.Actions.Upload);

        actionGroup.setPopup(true);

        actionGroup.add(new UploadTornaAction(apiTree));
//        actionGroup.addSeparator();
//        actionGroup.add(new UploadYapiAction(apiTree, myProject));
        group.add((ActionGroup) actionGroup);


        DefaultActionGroup exportGroup = new DefaultActionGroup();
        Presentation exportPresentation = exportGroup.getTemplatePresentation();
        exportPresentation.setText("导出");
        exportPresentation.setDescription("导出为文件");
        exportPresentation.setIcon(AllIcons.ToolbarDecorator.Export);

        group.addSeparator();
        group.add(new ExportAction(apiTree));
        group.add((ActionGroup) exportGroup);
        PopupHandler.installPopupMenu(apiTree, group, "RestfulApiOperationActions");
        this.setContent(mainPanel);

        filterRefresh();
    }

    private void initActionBar() {
        DefaultActionGroup group = new DefaultActionGroup();
        group.add(new RefreshApiAction(this::renderData));
        group.add(new SearchApiAction());
        group.add(new RequestMethodFilterAction(this::filterRefresh, myProject));
        group.add(new ProjectFilterAction(this::filterRefresh, myProject));
        group.add(CommonActionsManager.getInstance().createExpandAllAction(apiTree, apiTree));
        group.add(CommonActionsManager.getInstance().createCollapseAllAction(apiTree, apiTree));
        ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.TOOLWINDOW_CONTENT, group, true);
        setToolbar(actionToolbar.getComponent());
    }

    private void renderData() {
        DumbService.getInstance(myProject).smartInvokeLater(() -> rendingTree());
    }

    private void rendingTree() {
        TaskUtil.run(myProject, "Restful Cloud 加载项目Api", () -> {
            FrameworkExecute.buildApiMethod(myProject);
            filterRefresh();

        });

    }

    private void filterRefresh() {
        ApplicationManager.getApplication().runReadAction(() -> {
            StoreService storeService = BambooToolComponent.getStoreService();
            RestfulCloudConfig config = BambooToolComponent.getInstance(myProject).getState();
            boolean isShowDesc = storeService.selectIsShowDesc();
            List<BambooApiMethod> bambooApiMethods = storeService.searchApi(searchField.getText(), config.getSelectRequestTypes(), config.getSelectSoaTypes(), config.getSelectProjects(), myProject, isShowDesc);
            RootNode rootNode = PsiUtils.convertToRoot(bambooApiMethods);
            apiTree.setModel(new DefaultTreeModel(rootNode));
        });
    }

    private static class MyCellRenderer extends ColoredTreeCellRenderer {

        @Override
        public void customizeCellRenderer(@NotNull JTree tree, Object target, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            BaseNode node = null;
            if (target instanceof BaseNode) {
                node = (BaseNode<?>) target;
            }
            if (node == null) {
                return;
            }

            append(node.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
            setIcon(node.getIcon(true));
            if (target instanceof MethodNode) {
//                setToolTipText(((MethodNode) target).getToolTipText());
            }

            SpeedSearchUtil.applySpeedSearchHighlighting(this, this, false, true);
        }
    }

    private void navigateToMethod() {
        if (!apiTree.isEnabled()) {
            return;
        }
        Object component = apiTree.getLastSelectedPathComponent();
        if (!(component instanceof MethodNode)) {
            return;
        }
        MethodNode methodNode = (MethodNode) component;
        BambooApiMethod source = methodNode.getSource();

        source.navigate(true);
    }
}
